﻿using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using SharePointUtilitiesForDevelopers.Gateway;
using SharePointUtilitiesForDevelopers.Mapper;

namespace SharePointUtilitiesForDevelopers.Repository
{
    /// <summary>
    /// A repository for working with webs.
    /// </summary>
    public class SharePointWebRepository : ISharePointWebRepository
    {
        #region Fields

        private readonly ISharePointWebsServiceGateway _websServiceGateway;
        private readonly ISharePointListsServiceGateway _listsServiceGateway;
        private readonly IMapper<XElement, SharePointWeb> _webMapper;
        private readonly IMapper<XElement, SharePointContentType> _contentTypeMapper;
        private readonly IMapper<XElement, SharePointField> _fieldMapper;
        private readonly IMapper<XElement, SharePointList> _listMapper;

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="SharePointWebRepository"/> class.
        /// </summary>
        /// <param name="websServiceGateway">The webs service gateway.</param>
        /// <param name="listsServiceGateway">The lists service gateway.</param>
        /// <param name="webMapper">The web mapper.</param>
        /// <param name="contentTypeMapper">The content type mapper.</param>
        /// <param name="fieldMapper">The field mapper.</param>
        /// <param name="listMapper">The list mapper.</param>
        public SharePointWebRepository(
            ISharePointWebsServiceGateway websServiceGateway, 
            ISharePointListsServiceGateway listsServiceGateway,
            IMapper<XElement, SharePointWeb> webMapper,
            IMapper<XElement, SharePointContentType> contentTypeMapper,
            IMapper<XElement, SharePointField> fieldMapper,
            IMapper<XElement, SharePointList> listMapper)
        {
            _websServiceGateway = websServiceGateway;
            _listsServiceGateway = listsServiceGateway;
            _webMapper = webMapper;
            _contentTypeMapper = contentTypeMapper;
            _fieldMapper = fieldMapper;
            _listMapper = listMapper;
        }

        #endregion Constructors
        
        #region Methods

        /// <summary>
        /// Gets the web content types.
        /// </summary>
        /// <param name="siteUrl">The site URL.</param>
        /// <returns>A list of content types in the web.</returns>
        public IEnumerable<SharePointContentType> GetWebContentTypes(string siteUrl)
        {
            return _websServiceGateway.GetContentTypes(siteUrl, _contentTypeMapper);
        }

        /// <summary>
        /// Gets the web lists.
        /// </summary>
        /// <param name="siteUrl">The site URL.</param>
        /// <returns>A list of lists in the web.</returns>
        public IEnumerable<SharePointList> GetWebLists(string siteUrl)
        {
            return _listsServiceGateway.GetLists(siteUrl, _listMapper);
        }

        /// <summary>
        /// Gets the web site columns.
        /// </summary>
        /// <param name="siteUrl">The site URL.</param>
        /// <returns>A list of site columns in the web.</returns>
        public IEnumerable<SharePointField> GetWebSiteColumns(string siteUrl)
        {
            return _websServiceGateway.GetSiteColumns(siteUrl, _fieldMapper);
        }

        /// <summary>
        /// Gets the web site user list.
        /// </summary>
        /// <param name="siteUrl">The site URL.</param>
        /// <returns>The site user list for the specified site.</returns>
        public SharePointList GetWebSiteUserInfoList(string siteUrl)
        {
            return _listsServiceGateway.GetList(siteUrl, SharePointBuiltInListId.UserInfo, _listMapper);
        }

        /// <summary>
        /// Loads the web lists.
        /// </summary>
        /// <param name="web">The web.</param>
        public void LoadWebLists(SharePointWeb web)
        {
            var lists = GetWebLists(web.Url);
            web.Lists = lists.ToList().AsReadOnly(); 
        }

        /// <summary>
        /// Loads the web content types.
        /// </summary>
        /// <param name="web">The web.</param>
        public void LoadWebContentTypes(SharePointWeb web)
        {
            web.ContentTypes = GetWebContentTypes(web.Url).ToList().AsReadOnly();
        }

        /// <summary>
        /// Loads the web site columns.
        /// </summary>
        /// <param name="web">The web.</param>
        public void LoadWebSiteColumns(SharePointWeb web)
        {
            web.SiteColumns = GetWebSiteColumns(web.Url).ToList().AsReadOnly();    
        }

        /// <summary>
        /// Loads the web site user list.
        /// </summary>
        /// <param name="web">The web.</param>
        public void LoadWebSiteUserInfoList(SharePointWeb web)
        {
            web.SiteUserInfoList = GetWebSiteUserInfoList(web.Url);
        }

        /// <summary>
        /// Gets the web.
        /// </summary>
        /// <param name="siteUrl">The web URL.</param>
        /// <param name="options">Load options.</param>
        /// <returns>A <see cref="SharePointWeb"/>.</returns>
        public SharePointWeb GetWeb(string siteUrl, SharePointWebLoadOptions options)
        {
            // Get the web
            var web = _websServiceGateway.GetWeb(siteUrl, _webMapper);

            // Get the site user info list
            LoadWebSiteUserInfoList(web);
            
            // Get lists
            if(options.Lists)
            {
                LoadWebLists(web);
            }

            // Get content types
            if(options.ContentTypes)
            {
                LoadWebContentTypes(web);
            }

            // Get site columns
            if(options.SiteColumns)
            {
                LoadWebSiteColumns(web);
            }

            return web;
        }

        #endregion Methods
    }
}